#include <bits/stdc++.h>
#define int long long 
using namespace std;

// DFS 每层使用 状压 , 表示每层可能出现的情况
// 然后 DFS 时使用 记忆化, 降低时间复杂度
// 这里面状压时还不能使用 DP, 因为 DP 是直接开辟好了空间, 
// 空间太大了, 会运行错误, 这里面使用 mp 存储, 节省空间
// 


const int maxn = 21;
int n, m;
vector<int> rows; // 表示每层所有可能的情况
map<pair<int, int>, int> mp;

// 横向没有相邻的 1
bool valid(int val){
	if (val & (val>>1)) {
		return false;
	}
	return true;
}

// 递归出来所有可能的情况
int dfs(int row, int cur){
	if (row==n) {
		// 递归完成
		return 1;
	}
	
	if (mp.find({row, cur}) != mp.end()) { // 剪枝
		return mp[{row, cur}];
	}
	
	int cnt=0;
	for (int nxt: rows) {
		if ((cur&nxt)==0) { // 没有上下相邻的
			cnt += dfs(row+1, nxt);
		}
	}
	mp[{row, cur}] = cnt;
	return cnt;
}

void solve(){
	cin>>n>>m;
	
	// 先处理出所有 左右不相邻的, 这就是 所有每层可能的排列
	for (int i=0;i<(1<<m);i++) {
		if (valid(i)) {
			rows.push_back(i); 
		}
	}
	
	// 开始 dfs
	// 从第一层的所有可能的情况开始 dfs
	int ans = 0;
	for (int cur: rows) {
		ans += dfs(1, cur);
	}
	
	cout << ans << '\n';
}

signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	solve();
	return 0;
}
